package com.ruoyi.project.decision.service;

import com.ruoyi.project.decision.algorithms.CcfAlgorithm;
import com.ruoyi.project.decision.domain.CcfScores;
import com.ruoyi.project.decision.domain.DecisionScores;
import com.ruoyi.project.fusion.domain.HumanResourceScores;
import com.ruoyi.project.fusion.mapper.DataFusionMapper;
import com.ruoyi.project.knowledge.domain.OverallScores;
import com.ruoyi.project.knowledge.service.DataOptimizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DataDecisionService {
    @Autowired
    private DataOptimizationService dataOptimizationService;
    @Autowired
    private DataFusionMapper dataFusionMapper;

    public List<String> getEnterprises(String chainType, String scenario) {
        List<OverallScores> overallScores = dataOptimizationService.getOverallScores(chainType, scenario, 0);
        List<OverallScores> latestYearOverallScores = filterLatestYearData(overallScores);
        return latestYearOverallScores.stream()
                .map(OverallScores::getEnterpriseName)
                .distinct()
                .collect(Collectors.toList());
    }

    public List<CcfScores> getCcfScores(String chainType, String scenario, String enterprise) {
//        List<OverallScores> overallScores = dataOptimizationService.getOverallScores(chainType, scenario, 0);
//        List<OverallScores> latestYearOverallScores = filterLatestYearData(overallScores);
//        List<CcfScores> result = new CcfAlgorithm().compute(latestYearOverallScores, 0.75f, 0.25f);
        List<CcfScores> allResults = new ArrayList<>();
        int pageSize = 1000;  // 每次查询的条数，可根据实际情况调整
        int offset = 0;

        List<CcfScores> batchResults;
        do {
            batchResults = dataFusionMapper.getCcfScoreSInfos(chainType,scenario,offset,pageSize);
            allResults.addAll(batchResults);
            offset += pageSize; // 移动查询起始点
        } while (!batchResults.isEmpty()); // 直到查询不到数据，说明所有数据已获取完

        // 如果 enterprise 不为空，则按企业过滤
        if (enterprise != null && !enterprise.isEmpty()) {
            return allResults.stream()
                    .filter(score -> score.getEnterpriseNameA().equals(enterprise))
                    .collect(Collectors.toList());
        }
        return allResults;
    }

    public List<String> getProductType(String chainType, String scenario, int priorityType) {
        List<OverallScores> overallScores = dataOptimizationService.getOverallScores(chainType, scenario, priorityType);

        List<OverallScores> latestYearOverallScores = filterLatestYearData(overallScores);
        // 提取所有不同的产品类型
        return latestYearOverallScores.stream()
                .map(OverallScores::getProduct)
                .distinct()
                .collect(Collectors.toList());
    }

    public List<DecisionScores> getDecisionScores(String chainType, String scenario, int priorityType, int recommended) {
        List<OverallScores> overallScores = dataOptimizationService.getOverallScores(chainType, scenario, priorityType);

        // 1. 过滤出最新年份数据
        List<OverallScores> latestYearOverallScores = filterLatestYearData(overallScores);

        // 2. 按照 chainType, scenario, product 分组计算推荐系数
        List<DecisionScores> decisionScoresList = calculateRecommendedScores(latestYearOverallScores);

        // 3. 返回推荐系数最高的 recommended 个企业
        return getTopRecommended(decisionScoresList, recommended);
    }

    public List<OverallScores> filterLatestYearData(List<OverallScores> overallScores) {
        int latestYear = overallScores.stream()
                .map(scores -> Integer.parseInt(scores.getEvent().substring(0, 4)))
                .max(Comparator.naturalOrder())
                .orElseThrow(() -> new IllegalArgumentException("No event data found"));
        return overallScores.stream()
                .filter(scores -> Integer.parseInt(scores.getEvent().substring(0, 4)) == latestYear)
                .collect(Collectors.toList());
    }

    private List<DecisionScores> calculateRecommendedScores(List<OverallScores> overallScores) {
        Map<String, List<OverallScores>> groupedScores = overallScores.stream()
                .collect(Collectors.groupingBy(scores -> scores.getChainType() + "|" + scores.getScenario() + "|" + scores.getProduct()));

        List<DecisionScores> decisionScoresList = new ArrayList<>();
        for (Map.Entry<String, List<OverallScores>> entry : groupedScores.entrySet()) {
            List<OverallScores> group = entry.getValue();
            float averageScore = (float) group.stream().mapToDouble(OverallScores::getScore).average().orElse(0.0);
            float standardDeviation = (float) Math.sqrt(group.stream().mapToDouble(score -> Math.pow(score.getScore() - averageScore, 2)).average().orElse(0.0));

            for (OverallScores overallScore : group) {
                DecisionScores decisionScore = new DecisionScores();
                decisionScore.setChainType(overallScore.getChainType());
                decisionScore.setEnterpriseName(overallScore.getEnterpriseName());
                decisionScore.setScenario(overallScore.getScenario());
                decisionScore.setProduct(overallScore.getProduct());
                decisionScore.setEvent(overallScore.getEvent());
                decisionScore.setScore(overallScore.getScore());

                int recommendedScore = calculateRecommendedScore(overallScore, averageScore, standardDeviation);
                decisionScore.setRecommendedScore(recommendedScore);

                decisionScoresList.add(decisionScore);
            }
        }

        return decisionScoresList;
    }

    private int calculateRecommendedScore(OverallScores overallScore, float averageScore, float standardDeviation) {
        if (standardDeviation == 0) {
            return 5; // 如果标准差为0，说明所有分数都一样，返回中间值
        }
        float zScore = (overallScore.getScore() - averageScore) / standardDeviation;
        // 将 Z-Score 转换为 1-10 的范围
        int recommendedScore = Math.round((zScore + 2.5f) * 2); // 假设 Z-Score 分布在 -2.5 到 2.5 之间
        return Math.min(Math.max(recommendedScore, 1), 10); // 确保推荐系数在1到10分之间
    }

    private List<DecisionScores> getTopRecommended(List<DecisionScores> decisionScoresList, int recommended) {
        return decisionScoresList.stream()
                .sorted(Comparator.comparingInt(DecisionScores::getRecommendedScore).reversed())
                .limit(recommended)
                .collect(Collectors.toList());
    }
}
